const jsnes = require("jsnes");
class mynes{

    SCREEN_WIDTH = 256;
    SCREEN_HEIGHT = 240;
    FRAMEBUFFER_SIZE = this.SCREEN_WIDTH*this.SCREEN_HEIGHT;

    canvas_ctx;
    image;
    canvas;
    framebuffer_u8;
    framebuffer_u32;

    AUDIO_BUFFERING = 512;
    SAMPLE_COUNT = 4*1024;
    SAMPLE_MASK = this.SAMPLE_COUNT - 1;
    audio_samples_L = new Float32Array(this.SAMPLE_COUNT);
    audio_samples_R = new Float32Array(this.SAMPLE_COUNT);
    audio_write_cursor = 0;
    audio_read_cursor = 0;
    vue=null;
    frame=null;
    that=this;
    audio_ctx=null;
    script_processor=null;
    isRun=false

    constructor(){

    }
    nes = new jsnes.NES({
        onFrame: (framebuffer_24)=>{
            for(var i = 0; i < this.FRAMEBUFFER_SIZE; i++) this.framebuffer_u32[i] = 0xFF000000 | framebuffer_24[i];
        },
        onAudioSample: (l, r)=>{
            this.audio_samples_L[this.audio_write_cursor] = l;
            this.audio_samples_R[this.audio_write_cursor] = r;
            this.audio_write_cursor = (this.audio_write_cursor + 1) & this.SAMPLE_MASK;
        },
    });
    

    onAnimationFrame=function (){
        this.frame=window.requestAnimationFrame(this.onAnimationFrameBind);
        
        this.image.data.set(this.framebuffer_u8);
        // console.log(canvas_ctx)
        
        this.canvas_ctx.scale(2,2)
        this.canvas_ctx.putImageData(this.image, 0, 0);
        // console.log(devicePixelRatio) 
        // console.log(vue)
        // canvas_ctx.scale(2,2)
        this.canvas.style.width = this.vue.canvasSty.width;
        this.canvas.style.height = this.vue.canvasSty.height;

        this.nes.frame();
    }
    onAnimationFrameBind=this.onAnimationFrame.bind(this)
  

    audio_callback=function (event){
        var dst = event.outputBuffer;
        var len = dst.length;
        console.log(76666)
        // Attempt to avoid buffer underruns.
        if(((this.audio_write_cursor - this.audio_read_cursor) & this.SAMPLE_MASK) <this. AUDIO_BUFFERING){
            this.nes.frame();
        } 
        
        var dst_l = dst.getChannelData(0);
        var dst_r = dst.getChannelData(1);
        for(var i = 0; i < len; i++){
            var src_idx = (this.audio_read_cursor + i) & this.SAMPLE_MASK;
            dst_l[i] = this.audio_samples_L[src_idx];
            dst_r[i] = this.audio_samples_R[src_idx];
        }
        
        this.audio_read_cursor = (this.audio_read_cursor + len) & this.SAMPLE_MASK;
    }
    audio_callbackBind=this.audio_callback.bind(this)
    keyboard=function (callback, event){
        var player = 1;

        switch(event.keyCode){
            case 87: // w
                callback(player, jsnes.Controller.BUTTON_UP); break;
            case 83: // s
                callback(player, jsnes.Controller.BUTTON_DOWN); break;
            case 65: // a
                callback(player, jsnes.Controller.BUTTON_LEFT); break;
            case 68: // d
                callback(player, jsnes.Controller.BUTTON_RIGHT); break;
            case 85: // 'j' - qwerty, dvorak
            case 75: // 'k' - azerty
                callback(player, jsnes.Controller.BUTTON_A); break;
            case 74: // 'u' - qwerty, azerty
            case 73: // 'i' - dvorak
                callback(player, jsnes.Controller.BUTTON_B); break;
            case 16: // Tab
                callback(player, jsnes.Controller.BUTTON_SELECT); break;
            case 13: // Return
                callback(player, jsnes.Controller.BUTTON_START); break;
            default: break;
        }
    }

    nes_init=function (canvas_id){
        this.canvas = document.getElementById(canvas_id);
        this.canvas_ctx = this.canvas.getContext("2d");
        this.canvas_ctx.scale(0.5,0.5)
        this.image = this.canvas_ctx.getImageData(0, 0, this.SCREEN_WIDTH, this.SCREEN_HEIGHT);
        
        this.canvas_ctx.imageSmoothingQuality ='high'
        // canvas_ctx.imageSmoothingEnabled= false
        this.canvas_ctx.imageSmoothingEnabled=false
        // canvas_ctx.scale(1,1)
        this.canvas_ctx.fillStyle = "black";
        this.canvas_ctx.fillRect(0, 0, 466, 264);
        
        this.canvas.style.width = '466px';
        this.canvas.style.height = '264px';

        var buffer = new ArrayBuffer(this.image.data.length);
        this.framebuffer_u8 = new Uint8ClampedArray(buffer);
        this.framebuffer_u32 = new Uint32Array(buffer);
        
        
        // Setup audio.
        window.audio_ctx = new window.AudioContext();
        this.script_processor = window.audio_ctx.createScriptProcessor(this.AUDIO_BUFFERING, 0, 2);
        this.script_processor.onaudioprocess = this.audio_callbackBind;
        this.script_processor.connect(window.audio_ctx.destination);
    }

    nes_boot=function (rom_data){
        this.nes.loadROM(rom_data);
        this.frame=window.requestAnimationFrame(this.onAnimationFrameBind);
    }

    nes_load_data=function (canvas_id, rom_data,VUE){
        // this.nes.stop()
        window.cancelAnimationFrame(this.frame)
        if(window.audio_ctx){
            window.audio_ctx.close();
        }
        this.vue=VUE
        this.nes_init(canvas_id);
        this.nes_boot(rom_data);
        document.addEventListener('keydown', (event) => {this.keyboard(this.nes.buttonDown, event)});
        document.addEventListener('keyup', (event) => {this.keyboard(this.nes.buttonUp, event)});
    }

    nes_load_url=function (canvas_id, path,VUE){
        this.vue=VUE
        this.nes_init(canvas_id);
        var req = new XMLHttpRequest();
        req.open("GET", path);
        req.overrideMimeType("text/plain; charset=x-user-defined");
        req.onerror = () => console.log(`Error loading ${path}: ${req.statusText}`);
        
        req.onload = function() {
            if (this.status === 200) {
            nes_boot(this.responseText);
            } else if (this.status === 0) {
                // Aborted, so ignore error
            } else {
                req.onerror();
            }
        };
        
        req.send();
    }


}
window.MyNes=new mynes()
export default {
    mynes
}